#include "..\engine\memorymanager.h"
#include "string.h"
#include "..\math\math.h"
#include <strsafe.h>

string::string()
{
	EE_ZEROMEMORY(mpData, sizeof(mpData)); 
}
string::string(const char* pData)
{
	EE_ZEROMEMORY(mpData, sizeof(mpData)); 
	StringCchCopy(mpData, sizeof(mpData), pData); 
}

void string::empty()
{
	EE_ZEROMEMORY(mpData, sizeof(mpData)); 
}

bool string::equals(string& str, bool caseSensitive)
{
	const unsigned int aLength = str.length(); 
	const unsigned int bLength = length(); 

	if(aLength != bLength)
		return false; 

	const char* apData = str.c_str(); 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
			continue; 

		if(!caseSensitive) {
			uint aChar = apData[i];
			uint bChar = bpData[i];
			if(aChar >= (cuint)'A' && aChar <= (cuint)'Z')
				aChar -= ((cuint)'A');
			if(bChar >= (cuint)'A' && bChar <= (cuint)'Z')
				bChar -= ((cuint)'A');
			if(aChar == bChar)
				continue;
		}
		return false; 
	}

	return true; 
}

bool string::equals(const char* str, bool caseSensitive)
{	
	const unsigned int aLength = strlen(str); 
	const unsigned int bLength = length(); 

	if(aLength != bLength)
		return false; 

	const char* apData = str; 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
			continue; 

		if(!caseSensitive) {
			uint aChar = apData[i];
			uint bChar = bpData[i];
			if(aChar >= (cuint)'A' && aChar <= (cuint)'Z')
				aChar -= ((cuint)'A');
			if(bChar >= (cuint)'A' && bChar <= (cuint)'Z')
				bChar -= ((cuint)'A');
			if(aChar == bChar)
				continue;
		}
		return false; 
	}

	return true; 
}

bool string::equals(const string& str, bool caseSensitive)
{
	const unsigned int aLength = str.length(); 
	const unsigned int bLength = length(); 

	if(aLength != bLength)
		return false; 

	const char* apData = str.c_str(); 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
			continue; 

		if(!caseSensitive) {
			uint aChar = apData[i];
			uint bChar = bpData[i];
			if(aChar >= (cuint)'A' && aChar <= (cuint)'Z')
				aChar -= ((cuint)'A');
			if(bChar >= (cuint)'A' && bChar <= (cuint)'Z')
				bChar -= ((cuint)'A');
			if(aChar == bChar)
				continue;
		}
		return false; 
	}

	return true; 
}

bool string::equals(string& str, bool caseSensitive) const
{
	const unsigned int aLength = str.length(); 
	const unsigned int bLength = length(); 

	if(aLength != bLength)
		return false; 

	const char* apData = str.c_str(); 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
				continue; 

		if(!caseSensitive) {
			uint aChar = apData[i];
			uint bChar = bpData[i];
			if(aChar >= (cuint)'A' && aChar <= (cuint)'Z')
				aChar -= ((cuint)'A');
			if(bChar >= (cuint)'A' && bChar <= (cuint)'Z')
				bChar -= ((cuint)'A');
			if(aChar == bChar)
				continue;
		}
		
		return false; 
	}

	return true; 
}

bool string::equals(const char* str, bool caseSensitive) const
{
	const unsigned int aLength = strlen(str); 
	const unsigned int bLength = length(); 

	if(aLength != bLength)
		return false; 

	const char* apData = str; 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
			continue; 

		if(!caseSensitive) {
			uint aChar = apData[i];
			uint bChar = bpData[i];
			if(aChar >= (cuint)'A' && aChar <= (cuint)'Z')
				aChar -= ((cuint)'A');
			if(bChar >= (cuint)'A' && bChar <= (cuint)'Z')
				bChar -= ((cuint)'A');
			if(aChar == bChar)
				continue;
		}
		return false; 
	}

	return true; 
}

int string::compare(string& str)
{
	const unsigned int aLength = str.length(); 
	const unsigned int bLength = length(); 

	if(aLength < bLength)
		return 1; 

	if(bLength < aLength)
		return -1; 

	const char* apData = str.c_str(); 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
			continue; 

		return (apData[i] < bpData[i]) ? 1 : -1; 
	}

	return 0; 
}

int string::compare(string& str) const
{
	const unsigned int aLength = str.length(); 
	const unsigned int bLength = length(); 

	if(aLength < bLength)
		return 1; 

	if(bLength < aLength)
		return -1; 

	const char* apData = str.c_str(); 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
			continue; 

		return (apData[i] < bpData[i]) ? 1 : -1; 
	}

	return 0; 
}

int string::compare(const char* str)
{
	const unsigned int aLength = strlen(str); 
	const unsigned int bLength = length(); 

	if(aLength < bLength)
		return 1; 

	if(bLength < aLength)
		return -1; 

	const char* apData = str; 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
			continue; 

		return (apData[i] < bpData[i]) ? 1 : -1; 
	}

	return 0; 
}

int string::compare(const char* str) const
{
	const unsigned int aLength = strlen(str); 
	const unsigned int bLength = length(); 

	if(aLength < bLength)
		return 1; 

	if(bLength < aLength)
		return -1; 

	const char* apData = str; 
	const char* bpData = c_str(); 

	for(unsigned int i = 0;  i < aLength;  i++)
	{
		if(apData[i] == bpData[i])	
			continue; 

		return (apData[i] < bpData[i]) ? 1 : -1; 
	}

	return 0; 
}

int string::findLastOf(const char character)
{
	for(int i = 0, j = length();  i < j;  i++)
	{
		const int index = j - i - 1; 
		if(mpData[index] == character)
			return index; 
	}

	return -1; 
}

int string::findLastOf(const char character) const
{
	for(int i = 0, j = length();  i < j;  i++)
	{
		const int index = j - i - 1; 
		if(mpData[index] == character)
			return index; 
	}

	return -1; 
}

int string::find(const string& str)
{
	const int length = this->length(); 
	const int patternLength = str.length(); 
	if (length == 0 || patternLength == 0)
		return -1; 

	const char* pPattern = str.c_str(); 

	for(int i = 0;  i < length;  i++)
	{
		for(int j = 0;  j < patternLength;  j++)
		{
			if(i + j > length - 1)
				return -1; 
			if(pPattern[j] != mpData[i + j])
				break; 
			if(j == patternLength - 1)
				return i; 
		}
	}

	return -1; 
}

int string::find(const string& str) const
{
	const int length = this->length(); 
	const int patternLength = str.length(); 
	if (length == 0 || patternLength == 0)
		return -1; 

	const char* pPattern = str.c_str(); 

	for(int i = 0;  i < length;  i++)
	{
		for(int j = 0;  j < patternLength;  j++)
		{
			if(i + j > length - 1)
				return -1; 
			if(pPattern[j] != mpData[i + j])
				break; 
			if(j == patternLength - 1)
				return i; 
		}
	}

	return -1; 
}

string string::substring(const int start, const int len)
{
	const int _len = length(); 
	if(start >= _len)
		return string(); 
	const int endIdx = MIN(_len, start + len + 1); 

	char mSubstring[MAX_PATH] = {'\0'}; 
	const int substrLength = endIdx - start + 1; 
	if(substrLength == 0)
		return string(); 

	StringCchCopy(mSubstring, substrLength, &mpData[start]); 
	return string(mSubstring); 
}

string string::substring(const int start, const int len) const
{
	const int _len = length(); 
	if(start >= _len)
		return string(); 
	const int endIdx = MIN(_len, start + len + 1); 

	char mSubstring[MAX_PATH] = {'\0'}; 
	const int substrLength = endIdx - start + 1; 
	if(substrLength == 0)
		return string(); 

	StringCchCopy(mSubstring, substrLength, &mpData[start]); 
	return string(mSubstring); 
}

uint string::length()
{
	size_t length = 0; 
	StringCchLength(mpData,MAX_PATH,&length); 
	return (unsigned int)length; 
}

uint string::length() const
{
	size_t length = 0; 
	StringCchLength(mpData,MAX_PATH,&length); 
	return (unsigned int)length; 
}

void string::concat(const string& str)
{
	unsigned int startIdx = length(); 
	StringCchCat(&mpData[startIdx],MAX_PATH - startIdx, str.c_str()); 
}

void string::concat(const char* str)
{
	unsigned int startIdx = length(); 
	StringCchCat(&mpData[startIdx],MAX_PATH - startIdx, str);

}

void string::concat(const char letter)
{
	unsigned int startIdx = length(); 

	if(startIdx < MAX_PATH - 1)
	{
		mpData[startIdx] = letter;
	}

}

const char* string::c_str()
{
	return &mpData[0]; 
}

const char* string::c_str() const
{
	return (const char*)&mpData[0]; 
}

bool string::IsValid() const
{
	return (length() > 0); 

}